package cn.com.fattiger.framework.remoting.netty4.client;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.util.concurrent.TimeUnit;

import cn.com.fattiger.framework.remoting.client.AbstractClient;
import cn.com.fattiger.framework.remoting.netty4.client.channel.ClientChannelInitializer;
import cn.com.fattiger.framework.remoting.netty4.client.channel.ClientChannelManager;
import cn.com.fattiger.framework.remoting.netty4.client.channel.GlobalClientChannelManager;
import cn.com.fattiger.framework.remoting.netty4.client.handle.ClientReceivedHandle;
import cn.com.fattiger.framework.remoting.netty4.common.channel.ChannelManager;
import cn.com.fattiger.framework.remoting.netty4.common.protocol.handle.ReceivedHandle;
import cn.com.fattiger.framework.remoting.netty4.common.protocol.params.Constants;

public class NettyClient extends AbstractClient {

	private final Hosts host;
	private String hostName;
	private ReceivedHandle receivedHandle = null;
	private EventLoopGroup group = null;
	private Bootstrap b = null;
	private Channel nowChannel = null;

	public NettyClient(Hosts host) {
		super();
		this.host = host;
		this.hostName = host.getHost() + ":" + host.getPort();
		receivedHandle = new ClientReceivedHandle();
		group = new NioEventLoopGroup();

		b = new Bootstrap();
		b.group(group);
		b.channel(NioSocketChannel.class);

		b.option(ChannelOption.SO_KEEPALIVE, true);
		b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 60 * 1000);
		b.option(ChannelOption.SO_BACKLOG, 128);
		b.option(ChannelOption.SO_RCVBUF, 65535);
		b.option(ChannelOption.SO_SNDBUF, 65535);

		b.option(ChannelOption.TCP_NODELAY, true);
		b.option(ChannelOption.SO_REUSEADDR, true);

		b.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);

		b.handler(new ClientChannelInitializer(hostName, receivedHandle));
	}

	@Override
	public void connect() throws Exception {
		System.out.println("开始连接");
		ChannelFuture future = b.connect(host.getHost(), host.getPort());
		boolean ret = future.awaitUninterruptibly(Constants.DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);
		if (ret && future.isSuccess()) {
			Channel newChannel = future.channel();
			nowChannel = newChannel;
			ChannelManager channelManager = new ClientChannelManager(newChannel, this, hostName);
			channelManager.setConnectCount(host.getConnectionCount());
			GlobalClientChannelManager.put(hostName, channelManager);
			System.out.println("新连接:" + nowChannel + "\t" + GlobalClientChannelManager.getChannelManagerMap().get(hostName).size());
		}
	}

	@Override
	public void stop() {
		// TODO Auto-generated method stub
		if (nowChannel != null) {
			nowChannel.close();
			group.shutdownGracefully();
			nowChannel = null;
		}

	}

}
